package com.atguigu.gmall.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.util.HttpClientUtil;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.enums.ProcessStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.OrderDetailMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.atguigu.gmall.product.client.ProductFeignClient;
import com.atguigu.gmall.rabbit.constant.MqConst;
import com.atguigu.gmall.rabbit.service.RabbitService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: 李旭
 * @Time: 15:42
 * @Description:
 */
@Service
public class OrderInfoServiceImpl implements OrderInfoService {

    @Value("${ware.url}")
    private String WARE_URL;
    @Resource
    private ProductFeignClient productFeignClient;
    @Resource
    private OrderInfoMapper orderInfoMapper;
    @Resource
    private OrderDetailMapper orderDetailMapper;
    @Resource
    private RedisTemplate redisTemplate;
    //发送  消息丢失
    @Resource
    private RabbitService rabbitService;

    //提交订单
    @Override
    public Long submitOrder(OrderInfo orderInfo, String userId) {
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        StringBuilder sb = new StringBuilder();
        orderDetailList.forEach(orderDetail -> {
            BigDecimal price = productFeignClient.getPrice(orderDetail.getSkuId());
            orderDetail.setOrderPrice(price);
            //订单描述
            sb.append(orderDetail.getSkuName() + " ");
        });
        //总金额
        orderInfo.sumTotalAmount();
        //订单状态
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        //订单交易编号
        String outTradeNo = "ATGUIGU" + System.currentTimeMillis() + new Random().nextInt(1000);
        orderInfo.setOutTradeNo(outTradeNo);
        //订单描述
        if (sb != null && sb.length() > 100) {
            String substring = sb.toString().substring(0, 100);
            orderInfo.setTradeBody(substring);
        } else {
            orderInfo.setTradeBody(sb.toString());
        }
        //创建时间
        Calendar calendar = Calendar.getInstance();
        orderInfo.setCreateTime(calendar.getTime());
        //失效时间
        calendar.add(Calendar.MINUTE, 30);
        orderInfo.setExpireTime(calendar.getTime());
        //进度状态
        orderInfo.setProcessStatus(ProcessStatus.UNPAID.name());

        //userId
        orderInfo.setUserId(Long.parseLong(userId));
        orderInfoMapper.insert(orderInfo);
        //2.订单详情表
        List<String> skuIds = new ArrayList<>();
        List<OrderDetail> orderDetailList1 = orderInfo.getOrderDetailList();
        orderDetailList1.forEach(orderDetail -> {
            orderDetail.setOrderId(orderInfo.getId());
            skuIds.add(orderDetail.getSkuId().toString());
            orderDetailMapper.insert(orderDetail);
        });
        //1）将已经生成订单的商品从购物车中删除出去  canal
        String cacheH = RedisConst.USER_KEY_PREFIX + orderInfo.getUserId()
                + RedisConst.USER_CART_KEY_SUFFIX;
        redisTemplate.opsForHash().delete(cacheH, skuIds.toArray());
        //2）删除DB
        /*cartInfoMapper.delete(new QueryWrapper<CartInfo>()
                .eq("user_id", orderInfo.getUserId())
                .eq("is_checked", CartInfo.ISCHECKED));*/
        //删除DB
        rabbitService.sendMessage(MqConst.EXCHANGE_CRATE,
                MqConst.ROUTING_CRATE_DELETE,orderInfo.getUserId());
        return orderInfo.getId();
    }


    @Override
    public boolean checkStock(Long skuId, Integer skuNum) {
        // 远程调用http://www.gware.com /hasStock?skuId=10221&num=2
        String result = HttpClientUtil.doGet(WARE_URL + "/hasStock?skuId=" + skuId + "&num=" + skuNum);
        return "1".equals(result);
    }

    @Override
    public OrderInfo getOrderInfo(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        //订单详情
        orderInfo.setOrderDetailList(orderDetailMapper.
                selectList(new QueryWrapper<OrderDetail>()
                        .eq("order_id",orderId)));
        return orderInfo;
    }

    @Override
    public void cancelOrder(Long orderId) {
//            1、获取订单状态是否为未支付
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if(null != orderInfo){
            //未支付
            if(orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.name())){
//            2、是未支付更新订单状态为已关闭
                orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
                //进度状态也改为已关闭
                orderInfo.setProcessStatus(ProcessStatus.CLOSED.name());
                //更新订单
                orderInfoMapper.updateById(orderInfo);
                System.out.println("取消订单成功" + new Date());
            }
        }
    }
    //更新订单
    @Override
    public void updateOrderStatus(Long orderId, ProcessStatus processStatus) {
        OrderInfo orderInfo = new OrderInfo();
        orderInfo.setId(orderId);
        orderInfo.setOrderStatus(processStatus.getOrderStatus().name());
        orderInfo.setProcessStatus(processStatus.name());
        orderInfoMapper.updateById(orderInfo);
    }
    // 发送消息，通知仓库
    @Override
    public void sendOrderStatus(Long orderId) {
        //1:更新订单状态 为已通知仓储
        updateOrderStatus(orderId,ProcessStatus.NOTIFIED_WARE);
        //2:根据ID查询订单数据
        OrderInfo orderInfo = getOrderInfo(orderId);
        //3:组织数据
        Map<String, Object> resultMap = initWareOrder(orderInfo);
        //4:通知仓库
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_WARE_STOCK,
                MqConst.ROUTING_WARE_STOCK, JSONObject.toJSONString(resultMap));
    }

    //组织发送给仓库的所需要的数据
    @Override
    public Map<String,Object> initWareOrder(OrderInfo orderInfo){
        Map<String,Object> resultMap = new HashMap<>();

        resultMap.put("orderId",orderInfo.getId());
        resultMap.put("consignee",orderInfo.getConsignee());
        resultMap.put("consigneeTel",orderInfo.getConsigneeTel());
        resultMap.put("orderComment",orderInfo.getOrderComment());
        resultMap.put("orderBody",orderInfo.getTradeBody());
        resultMap.put("deliveryAddress",orderInfo.getDeliveryAddress());
        resultMap.put("paymentWay","ONLINE".equals(orderInfo.getPaymentWay())?"2":"1");
        //订单详情
        List<Map> details = orderInfo.getOrderDetailList().stream().map(orderDetail -> {
            Map map = new HashMap();
            map.put("skuId", orderDetail.getSkuId());
            map.put("skuName", orderDetail.getSkuName());
            map.put("skuNum", orderDetail.getSkuNum());
            return map;
        }).collect(Collectors.toList());
        resultMap.put("details",details);
        //传入仓库ID
        resultMap.put("wareId",orderInfo.getWareId());

        return resultMap;
    }

    @Override
    @Transactional
    public List<Map> orderSplit(Long orderId, String wareSkuMap) {
        //前提：转成ListMap
        List<Map> mapList = JSONObject.parseArray(wareSkuMap, Map.class);
        //1:根据原订单ID查询原始订单信息（此原始订单对应的订单详情集合信息）
        OrderInfo orderInfoOrigin = getOrderInfo(orderId);
        //子订单集合
        List<Map> listMap = mapList.stream().map(map -> {
            //遍历仓库   每一个仓库就是map
            //一个仓库是一张订单
            //子订单  数据来原于父订单
            OrderInfo subOrderInfo = new OrderInfo();
            BeanUtils.copyProperties(orderInfoOrigin,subOrderInfo);
            //解决问题：
            //1) 设置子订单的ID为null
            subOrderInfo.setId(null);
            //2) 设置父ID
            subOrderInfo.setParentOrderId(orderInfoOrigin.getId());
            //保存子订单的订单详情
            List<String> skuIds = (List<String>) map.get("skuIds");
            //一个仓库有多个子订单详情集合5RGB
            List<OrderDetail> subOrderDetailList = new ArrayList<>();
            for (String skuId : skuIds) {
                // 根据 skuId +  父Id
                //原始订单详情集合
                // Map 1 : {"wareId":"1","skuIds":["2","10"]}
                // Map 2 : {"wareId":"2","skuIds":["3"]}
                List<OrderDetail> orderDetailListOrigin = orderInfoOrigin.getOrderDetailList();
                for (OrderDetail orderDetailOrigin : orderDetailListOrigin) {
                    if(orderDetailOrigin.getSkuId().toString().equals(skuId)){
                        subOrderDetailList.add(orderDetailOrigin);
                        break;
                    }
                }
            }
            //3)设置子订单的订单详情的引用
            subOrderInfo.setOrderDetailList(subOrderDetailList);
            //计算总金额
            subOrderInfo.sumTotalAmount();
            //保存子订单
            orderInfoMapper.insert(subOrderInfo);

            //更新当前子订单对应的多个订单详情（设置外键）
            subOrderInfo.getOrderDetailList().forEach(orderDetail -> {
                orderDetail.setOrderId(subOrderInfo.getId());
                orderDetailMapper.updateById(orderDetail);
            });
            return initWareOrder(subOrderInfo);
        }).collect(Collectors.toList());
        return mapList;
    }


}
